package nl.haemers.data.reflection 
{
	import flash.utils.getDefinitionByName;
	import nl.haemers.data.constants.DataTypes;
	import nl.haemers.data.constants.ReflectionConstants;
	import nl.haemers.data.reflection.IMetadatas;
	import nl.haemers.data.reflection.Type;
	import nl.haemers.data.serializers.ObjectSerializer;
	import nl.haemers.data.utils.ObjectUtils;
	/**
	 * ... 
	 * @author Jonathan Haemers
	 */
	public class Variable implements IVariable 
	{
		private var _name				:String;
		private var _propName			:String;
		private var _access				:String;
		private var _dataType			:String;
		private var _xmlDataType		:String;
		private var _declaredBy			:String;
		
		private var _level				:int;
		private var _metadatas			:IMetadatas;
		
		private var _hasSerialize		:Boolean;
		private var _objType			:Type;
		private var _ignore				:Boolean;
		private var _overwriteable		:Boolean;
		
		public function Variable(description:XML) : void
		{
			init(description);
		}
		
		/** Public methods **/
		public function get metadatas() : IMetadatas 
		{
			return _metadatas;
		}
		
		public function hasSerialize() : Boolean 
		{
			return _hasSerialize;
		}
		
		public function hasParent() : Boolean 
		{
			return false;
		}
		
		public function toString() : String
		{
			return _name;
		}
		
		/** Getters & Setters **/
		public function get name() : String 
		{
			return _name;
		}
		
		/**
		 * Real name of the property.
		 */
		public function get propertyName() : String
		{
			return _propName;
		}
		
		public function get dataType() : String 
		{
			return _dataType;
		}
		
		public function get objectType() : Type 
		{
			if (_objType == null && !ObjectUtils.isDataType(_dataType))
			{
				_objType = createType(this.dataType);
			}
			
			return _objType;
		}
		
		/**
		 * Name of the parent who uses the Accessor.
		 */
		public function get declaredBy():String 
		{
			return _declaredBy;
		}
		
		public function get level() : int 
		{
			return -1;
		}
		
		public function get ignore() : Boolean
		{
			return _ignore;
		}
		/**
		 * Variable is always writeable.
		 */
		public function get writeable() : Boolean
		{
			return true;
		}
		
		public function get overwriteable() : Boolean
		{
			return _overwriteable;
		}
		/** Protected methods **/
		
		/** Private methods **/
		
		/** Static methods **/
		private function init(xml:XML) : void
		{
			//var variable:Variable = new Variable();
			this._metadatas = new Metadatas(xml);
			var serialize:IMetadata = this._metadatas.getMetadata(ReflectionConstants.OBJECT_ATTRIBUTE);
			this._hasSerialize = serialize != null;
			
			this._name = xml.@name;
			if (this._hasSerialize)
			{
				if (serialize.args.hasArg(ReflectionConstants.ATTRIBUTE_NAME))
					this._name = serialize.args.getArg(ReflectionConstants.ATTRIBUTE_NAME).value;
					
				if (serialize.args.hasArg(ReflectionConstants.ATTRIBUTE_IGNORE))
					this._ignore = serialize.args.getArg(ReflectionConstants.ATTRIBUTE_IGNORE).value === "true";
					
				if (serialize.args.hasArg(ReflectionConstants.OVERWRITEABLE))
					this._overwriteable = serialize.args.getArg(ReflectionConstants.OVERWRITEABLE).value === "true";
			}
			
			this._propName = xml.@name;
			
			this._dataType = xml.@type;
			this._declaredBy = xml.@declaredBy;
			
			if (ObjectUtils.isVector(this.dataType) || ObjectUtils.isDictionary(this.dataType))
			{
				this._xmlDataType = this._dataType;
				this._dataType = ObjectUtils.isVector(this.dataType) ? DataTypes.VECTOR : DataTypes.DICTIONARY;
			}
			
		}
		
		private function createType(type:String) : Type
		{
			var classRef:Class = getDefinitionByName(type) as Class;
			return ObjectSerializer.getType(classRef);
		}
		
	}

}